今天主要來講如何新增View檢視頁面,以及資料傳遞的一些作法。
延續前一天的最後講到ActionResult的範例:
// GET: Demo
public ActionResult Index()
{
return View();
}
當我們將程式執行起來並進入URL https://localhost:44349/Demo/Index 的時候,會看到畫面如下的錯誤,表示找不到動作方法相對應的View畫面。當動作方法回傳的是ViewResult時,我們其實應該要為它新增一個檢視頁面。
新增檢視頁面的步驟如下:
在 return View();
的View()
上方按下滑鼠右鍵,點選「新增檢視」
選擇「MVC5檢視」並點擊「加入」
「檢視名稱」照預設會與動作方法名稱相符,範本維持預設選擇「Empty(沒有模型)」,預設勾選為「使用版面配置頁」,這邊我們都先不修改,直接按下「加入」即會自動生成View檔案。
產生後畫面如下,可以發現檔案是生成在「Views」 → 「Demo」資料夾底下,自動與控制器名稱對應好了呢!
生成的View是屬於.cshtml
檔,顧名思義它可以讓我們在裡面同時撰寫C#與HTML的語法,但在使用C#語法時,必須在前面先加上@
符號,如果有包含整句程式碼則使用大括號{ }
將程式碼區塊包起來,這個稱為「Razor語法」;另外如果在C#語法後還要接HTML格式則要空一格或換行。比如我們隨意新增程式碼如下:
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<div>
今年是:@DateTime.Now.Year 年
</div>
直接在View程式碼上按下滑鼠右鍵,點擊「在瀏覽器中檢視」可以看到顯示結果如下圖:
另外因為在新增View的時候有勾選「使用版面配置頁」,所以看到一樣會套用預設Layout版面。
在做少量的資料傳遞時,我們可以透過ViewData、ViewBag、TempData三種物件來存取傳到View。
ViewData的存取是透過Key/Value的形式,Key必須是唯一,寫法是 ViewData["Key"] = Value;
例如在 DemoController
底下Index()
方法,新增Code如下:
// GET: Demo
public ActionResult Index()
{
ViewData["Name"] = "陳小強";
return View();
}
然後在對應的View頁面修改成如下方Code:
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<div>
今年是:@DateTime.Now.Year 年
<br />
我的名字是: @ViewData["Name"]
</div>
顯示結果如下圖:
ViewBag的使用方式和ViewData類似,差別在於ViewBag是使用動態(dynamic)型別,可以省去手動轉型的麻煩,但相對ViewData執行速度較慢。(但少量資料我們其實感受不到)
寫法是 ViewBag.屬性 = 屬性值;
我們可以將ViewData的範例改寫如下:
// GET: Demo
public ActionResult Index()
{
//ViewData["Name"] = "陳小強";
ViewBag.Name = "陳小強";
return View();
}
View
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<div>
今年是:@DateTime.Now.Year 年
<br />
我的名字是: @ViewBag.Name
</div>
顯示結果和ViewData一樣:
TempData 和 ViewData 寫法很像,都是透過Key/Value的形式存取資料,
寫法是:TempData["Key"] = Value;
但差別在於ViewData的生命週期只有一次Request(請求),請求完就會被刪除了。而TempData會暫時存在Session中,最多可以經導向一次,在二次導向頁面時才會被清除。
範例如下:
// GET: Demo
public ActionResult Index()
{
//ViewData["Name"] = "陳小強";
//ViewBag.Name = "陳小強";
TempData["Name"] = "陳小強";
return View();
}
View
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<div>
今年是:@DateTime.Now.Year 年
<br />
我的名字是: @TempData["Name"]
</div>
顯示結果和ViewData一樣:
接著我們示範一下TempData經由一次導向後仍可傳遞的範例,並且看看是否ViewBag和ViewData無法存活到導向頁面。
我們改寫一下Index()
的方法內容,並建立一個新的動作方法叫ShowTempData()
。流程是當呼叫Index()
後,會導向到ShowTempData()
這個動作與顯示對應的View頁面,Code如下:
// GET: Demo
public ActionResult Index()
{
TempData["Name"] = "陳小強";
ViewData["Name"] = "陳小強";
ViewBag.Name = "陳小強";
return RedirectToAction("ShowTempData");
}
public ActionResult ShowTempData()
{
return View();
}
新增ShowTempData()
方法的View頁面如下:
@{
ViewBag.Title = "ShowTempData";
}
<h2>ShowTempData</h2>
<div>
[使用TempData傳遞]
我的名字是: @TempData["Name"]
<br />
[使用ViewData傳遞]
我的名字是: @ViewData["Name"]
<br />
[使用ViewBag傳遞]
我的名字是: @ViewBag.Name
</div>
當執行網址~Demo/Index
時,發現網址會導向到~Demo/ShowTempData
,顯示結果如下:
由此可見確實只有TempData能夠成功被傳遞~
上面提到ViewData和ViewBag的其中一個差異在於手動轉型的麻煩,我們用一個範例說明:
ShowMembers()
方法 public ActionResult ShowMembers()
{
return View();
}
ShowMembers()
的View,一樣使用預設的條件建立即可,建立後View Code如下:
@{
ViewBag.Title = "ShowMembers";
}
<h2>ShowMembers</h2>
Member
,並簡單新增幾個屬性,Code如下: public class Member
{
//新增屬性可使用快捷鍵prop產生
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
ShowMembers()
方法新增幾行Code,用以建立幾個Member
物件,並將這些物件加入List集合內,最後讓ViewData攜帶此List物件傳遞,Code如下: public ActionResult ShowMembers()
{
var memberA = new Member() { Id = 1, Name = "Alex", Age = 12 };
var memberB = new Member() { Id = 2, Name = "Ben", Age = 34 };
var memberC = new Member() { Id = 3, Name = "Carol", Age = 56 };
var memberList = new List<Member>() { memberA, memberB, memberC };
ViewData["Members"] = memberList;
return View();
}
※這邊可以發現ViewData不只能傳遞簡單型別資料,也能傳遞物件哦!
5. 在ShowMembers()
的View修改成以下Code:
@using MyFirstWebApp.Models
@{
ViewBag.Title = "ShowMembers";
}
<h2>ShowMembers</h2>
<div>
@{
foreach (var member in ViewData["Members"] as List<Member>)
{
<label>會員編號:</label> @member.Id
<br />
<label>會員姓名:</label> @member.Name
<br />
<label>年齡:</label> @member.Age
<hr />
}
}
</div>
這邊利用foreach迴圈將ViewData["Members"]
傳遞的List<Member>
物件內資料全部顯示出來,並且可以發現這裡必須使用 as
關鍵字來指定ViewData["Members"]
的型別。
另外,因為Member
類別是在Models資料夾中,所以必須在上面引用該資料夾才能成功指定型別。
6. 在ShowMembers的View頁面按滑鼠右鍵,點擊「在瀏覽器中檢視」,顯示畫面如下圖:
7. 接著將ViewData改寫成ViewBag的方式,請參考下方Code:
DemoController:
public ActionResult ShowMembers()
{
var memberA = new Member() { Id = 1, Name = "Alex", Age = 12 };
var memberB = new Member() { Id = 2, Name = "Ben", Age = 34 };
var memberC = new Member() { Id = 3, Name = "Carol", Age = 56 };
var memberList = new List<Member>() { memberA, memberB, memberC };
//ViewData["Members"] = memberList;
ViewBag.Members = memberList;
return View();
}
View:
@{
ViewBag.Title = "ShowMembers";
}
<h2>ShowMembers</h2>
<div>
@{
foreach (var member in ViewBag.Members)
{
<label>會員編號:</label> @member.Id
<br />
<label>會員姓名:</label> @member.Name
<br />
<label>年齡:</label> @member.Age
<hr />
}
}
</div>
從View頁面的Code可以發現,在foreach迴圈的地方不需要指定ViewBag.Members
的型別也能成功執行,當然因此不需要引用Models資料夾裡的Member類別了。比較起來是否覺得ViewBag寫法簡略一點呢?
今天介紹了如何新增View,以及幾種資料傳遞的方式。在寫View的程式碼時會常用到許多HTML標籤的語法,但因為主題重點不是在說明HTML,所以就不一一解釋每行Code了。明天我們繼續講關於資料傳遞的其他模式,See U Tomorrow~~
※小弟不才,在軟體的世界還只是個小菜雞,如果內容有任何謬誤或問題,還請各位大神前輩們多多批評指教~歡迎下方留言討論^^